//////////////////////////////////////////////////////////////////////////
// NO_Base
//////////////////////////////////////////////////////////////////////////
#ifndef	NO_Base_H
#define NO_Base_H

//////////////////////////////////////////////////////////////////////////
#include "NO_Includes.h"
#include "NO_TypeQualifier.h"

//////////////////////////////////////////////////////////////////////////
class NO_Type;

//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_IBase
{
public:
	//////////////////////////////////////////////////////////////////////////
	NO_IBase();
	virtual ~NO_IBase();

	//////////////////////////////////////////////////////////////////////////
	virtual NO_Type const &	getDerivedType	(void)		const = 0;
	virtual NO_Type const &	getBaseType		(void)		const = 0;
	virtual NO_Int32		getOffset		(void)		const = 0;
	virtual NO_Value*		getBase			(NO_Value&)	const = 0;
	
	//////////////////////////////////////////////////////////////////////////
	NO_Int32 getID(void) const;
	
private:
	//////////////////////////////////////////////////////////////////////////
	// friends
	//////////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////////
	friend class NO_BaseFriend;
	
	//////////////////////////////////////////////////////////////////////////
	NO_UInt32 id;
	NO_IBase* next;
};

//////////////////////////////////////////////////////////////////////////
template<class B, class D>
class NO_Base : public NO_IBase
{
public:
	//////////////////////////////////////////////////////////////////////////
	const NO_Type&	getBaseType(void)	const {return NO_TypeID<B>::type();}
	const NO_Type&	getDerivedType(void)const {return NO_TypeID<D>::type();}
	
	//////////////////////////////////////////////////////////////////////////
	NO_Int32 getOffset(void) const 
	{
		D* dp = reinterpret_cast<D*>(1000000);
		B* bp = static_cast<B*>(dp);
		return ((reinterpret_cast<ptrdiff_t>(bp))-(reinterpret_cast<ptrdiff_t>(dp)));
	}
	
	//////////////////////////////////////////////////////////////////////////
	NO_Value*	getBase(NO_Value& obj)	const 
	{
		D* derived = noGetDataException<D>(obj);
		B* base = static_cast<B*>(derived);
		return new NO_ReferenceValue<B>(base, &obj);
	}
};

//////////////////////////////////////////////////////////////////////////
// class NO_BaseFriend definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_BaseFriend  
{
protected:
	//////////////////////////////////////////////////////////////////////////
	const NO_IBase*	getNext	(const NO_IBase*)		const;
	void			setNext	(NO_IBase*, NO_IBase*)	const;
	void			setID	(NO_IBase*, NO_UInt32)	const;
};

//////////////////////////////////////////////////////////////////////////
// class NO_BaseList definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_BaseList : public NO_BaseFriend
{
public:
	//////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_BaseList(void);
	~NO_BaseList(void);
	
	//////////////////////////////////////////////////////////////////////////
	// modify
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	NO_Boolean addBase(NO_IBase* obj);
	
	//////////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	const NO_IBase* findBaseImpl(const NO_Int8* name)	const;
	const NO_IBase* findBaseImpl(NO_UInt32 ID)			const;

	//////////////////////////////////////////////////////////////////////////
	const NO_IBase* beginBaseImpl	(void) const;
	const NO_IBase* endBaseImpl		(void) const;
	const NO_IBase* nextBaseImpl	(const NO_IBase*) const;

private:
	//////////////////////////////////////////////////////////////////////
	NO_IBase* first;
	NO_IBase* last;
};

//////////////////////////////////////////////////////////////////////////
// class NO_BaseList definition
//////////////////////////////////////////////////////////////////////////
class NO_DLL_TAL NO_NoneBases 
{
public:
	//////////////////////////////////////////////////////////////////////
	// con/destruction
	//////////////////////////////////////////////////////////////////////
	
	//////////////////////////////////////////////////////////////////////
	NO_NoneBases(void);
	~NO_NoneBases(void);
	
	//////////////////////////////////////////////////////////////////////////
	// retrieve
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	const NO_IBase* findBaseImpl(const NO_Int8* name)	const;
	const NO_IBase* findBaseImpl(NO_UInt32 ID)			const;

	//////////////////////////////////////////////////////////////////////////
	const NO_IBase* beginBaseImpl	(void) const;
	const NO_IBase* endBaseImpl		(void) const;
	const NO_IBase* nextBaseImpl	(const NO_IBase*) const;
};

#endif

